﻿namespace Voxel2Unity
{
    using System;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public class VoxData
    {
        public string Name;
        public Color[] Palatte;
        public int SizeX;
        public int SizeY;
        public int SizeZ;
        public byte[] Version;
        public int[,,] Voxels;

        public void Flip(Voxel2Unity.Axis _axis)
        {
            for (int i = 0; i < ((_axis != Voxel2Unity.Axis.X) ? ((float) this.SizeX) : (this.SizeX * 0.5f)); i++)
            {
                for (int j = 0; j < ((_axis != Voxel2Unity.Axis.Y) ? ((float) this.SizeY) : (this.SizeY * 0.5f)); j++)
                {
                    for (int k = 0; k < ((_axis != Voxel2Unity.Axis.Z) ? ((float) this.SizeZ) : (this.SizeZ * 0.5f)); k++)
                    {
                        int num4 = (_axis != Voxel2Unity.Axis.X) ? i : ((this.SizeX - i) - 1);
                        int num5 = (_axis != Voxel2Unity.Axis.Y) ? j : ((this.SizeY - j) - 1);
                        int num6 = (_axis != Voxel2Unity.Axis.Z) ? k : ((this.SizeZ - k) - 1);
                        int num7 = this.Voxels[i, j, k];
                        this.Voxels[i, j, k] = this.Voxels[num4, num5, num6];
                        this.Voxels[num4, num5, num6] = num7;
                    }
                }
            }
        }

        public VoxData GetLod(int level)
        {
            return this;
        }

        public VoxData GetLODVoxelData(int lodLevel)
        {
            if (((this.SizeX <= 1) || (this.SizeY <= 1)) || (this.SizeZ <= 1))
            {
                return null;
            }
            lodLevel = Mathf.Clamp(lodLevel, 0, 8);
            if (lodLevel <= 1)
            {
                return this;
            }
            if (((this.SizeX <= lodLevel) && (this.SizeY <= lodLevel)) && (this.SizeZ <= lodLevel))
            {
                return null;
            }
            VoxData data = new VoxData {
                SizeX = Mathf.Max(Mathf.CeilToInt(((float) this.SizeX) / ((float) lodLevel)), 1)
            };
            int[] values = new int[] { Mathf.CeilToInt(((float) this.SizeY) / ((float) lodLevel)) };
            data.SizeY = Mathf.Max(values);
            int[] numArray2 = new int[] { Mathf.CeilToInt(((float) this.SizeZ) / ((float) lodLevel)) };
            data.SizeZ = Mathf.Max(numArray2);
            data.Version = this.Version;
            data.Palatte = this.Palatte;
            data.Voxels = new int[data.SizeX, data.SizeY, data.SizeZ];
            for (int i = 0; i < data.SizeX; i++)
            {
                for (int j = 0; j < data.SizeY; j++)
                {
                    for (int k = 0; k < data.SizeZ; k++)
                    {
                        data.Voxels[i, j, k] = this.GetMajorityColorIndex(i * lodLevel, j * lodLevel, k * lodLevel, lodLevel);
                    }
                }
            }
            return data;
        }

        public int GetMajorityColorIndex(int x, int y, int z, int lodLevel)
        {
            x = Mathf.Min(x, this.SizeX - 2);
            y = Mathf.Min(y, this.SizeY - 2);
            z = Mathf.Min(z, this.SizeZ - 2);
            int num = (int) Mathf.Pow((float) lodLevel, 3f);
            int[] numArray = new int[num];
            for (int i = 0; i < lodLevel; i++)
            {
                for (int m = 0; m < lodLevel; m++)
                {
                    for (int n = 0; n < lodLevel; n++)
                    {
                        if ((((x + i) > (this.SizeX - 1)) || ((y + m) > (this.SizeY - 1))) || ((z + n) > (this.SizeZ - 1)))
                        {
                            numArray[(((i * lodLevel) * lodLevel) + (m * lodLevel)) + n] = 0;
                        }
                        else
                        {
                            numArray[(((i * lodLevel) * lodLevel) + (m * lodLevel)) + n] = this.Voxels[x + i, y + m, z + n];
                        }
                    }
                }
            }
            int[] numArray2 = new int[num];
            int num5 = 1;
            int index = 0;
            for (int j = 0; j < num; j++)
            {
                numArray2[j] = (numArray[j] != 0) ? 1 : 0;
            }
            for (int k = 0; k < num; k++)
            {
                for (int num9 = 0; num9 < num; num9++)
                {
                    if (((k != num9) && (numArray[k] != 0)) && (numArray[k] == numArray[num9]))
                    {
                        numArray2[k]++;
                        if (numArray2[k] > num5)
                        {
                            num5 = numArray2[k];
                            index = k;
                        }
                    }
                }
            }
            return numArray[index];
        }

        public void Rotate(Voxel2Unity.Axis _axis, bool reverse = false)
        {
            int sizeX = this.SizeX;
            int sizeY = this.SizeY;
            int sizeZ = this.SizeZ;
            int[,,] numArray = null;
            switch (_axis)
            {
                case Voxel2Unity.Axis.X:
                    sizeY = this.SizeZ;
                    sizeZ = this.SizeY;
                    numArray = new int[sizeX, sizeY, sizeZ];
                    for (int i = 0; i < this.SizeX; i++)
                    {
                        for (int j = 0; j < this.SizeY; j++)
                        {
                            for (int k = 0; k < this.SizeZ; k++)
                            {
                                numArray[i, k, j] = this.Voxels[i, j, k];
                            }
                        }
                    }
                    this.SizeY = sizeY;
                    this.SizeZ = sizeZ;
                    this.Voxels = numArray;
                    if (reverse)
                    {
                        this.Flip(Voxel2Unity.Axis.Z);
                    }
                    else
                    {
                        this.Flip(Voxel2Unity.Axis.Y);
                    }
                    break;

                case Voxel2Unity.Axis.Y:
                    sizeX = this.SizeZ;
                    sizeZ = this.SizeX;
                    numArray = new int[sizeX, sizeY, sizeZ];
                    for (int m = 0; m < this.SizeX; m++)
                    {
                        for (int n = 0; n < this.SizeY; n++)
                        {
                            for (int num9 = 0; num9 < this.SizeZ; num9++)
                            {
                                numArray[num9, n, m] = this.Voxels[m, n, num9];
                            }
                        }
                    }
                    this.SizeX = sizeX;
                    this.SizeZ = sizeZ;
                    this.Voxels = numArray;
                    if (reverse)
                    {
                        this.Flip(Voxel2Unity.Axis.X);
                    }
                    else
                    {
                        this.Flip(Voxel2Unity.Axis.Z);
                    }
                    break;

                case Voxel2Unity.Axis.Z:
                    sizeX = this.SizeY;
                    sizeY = this.SizeX;
                    numArray = new int[sizeX, sizeY, sizeZ];
                    for (int num10 = 0; num10 < this.SizeX; num10++)
                    {
                        for (int num11 = 0; num11 < this.SizeY; num11++)
                        {
                            for (int num12 = 0; num12 < this.SizeZ; num12++)
                            {
                                numArray[num11, num10, num12] = this.Voxels[num10, num11, num12];
                            }
                        }
                    }
                    this.SizeX = sizeX;
                    this.SizeY = sizeY;
                    this.Voxels = numArray;
                    if (reverse)
                    {
                        this.Flip(Voxel2Unity.Axis.Y);
                    }
                    else
                    {
                        this.Flip(Voxel2Unity.Axis.X);
                    }
                    break;
            }
        }

        public int VoxelNum
        {
            get
            {
                int num = 0;
                for (int i = 0; i < this.SizeX; i++)
                {
                    for (int j = 0; j < this.SizeY; j++)
                    {
                        for (int k = 0; k < this.SizeZ; k++)
                        {
                            if (this.Voxels[i, j, k] != 0)
                            {
                                num++;
                            }
                        }
                    }
                }
                return num;
            }
        }
    }
}

